/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef _SERIALSTD_HPP_
#define _SERIALSTD_HPP_

#include "drivers/bus/serial/serial.hpp"

#ifdef LINUX_OS
#include <termios.h>
#include <unistd.h>
#endif

#include <string>

class CSerialStd : public ASRobo::Drivers::Bus::CSerial
{
public:
  /**
   * Advanced constructor
   *
   */
  CSerialStd(int aId, const std::string &aBusName);

  /**
   * Destructor.
   */
  virtual ~CSerialStd();

  /**
   * Derived function implementing the real opening of the device.
   *
   * @return                KBusStatusOK on ok, KBusStatusError on error.
   */
  EBusStatus Open(void);


  /**
   * Reads data from serial port. The read only reads as much data as is available.
   *
   * @param buffer          Buffer to read data to, must be atleast 'readb' bytes.
   * @param buffer_size     Storage available
   * @return                Negative on error, otherwise the number of bytes
   *                        stored on the 'buffer'
   */
  int Read(unsigned char *buffer, int buffer_size);


  /**
   * Writes data to serial port. Does not guarantee that the whole block
   * is sent.
   *
   * @param buffer          Buffer to write data from. Must be atleast
   *                        'buffer_size' bytes long.
   * @param buffer_size     Lenght of the data to write.
   * @return                Negative on error, otherwise number of bytes
   *                        really sent
   */
  int Write(const unsigned char *buffer, int buffer_size);


  /**
   * Reads data from serial port. Specify timeout to determine when
   * the call times out.
   *
   * @param buffer          Buffer to read data to, must be atleast 'readb' bytes.
   * @param block_size      Bytecount to read from device.
   * @param timeout_ms      Timeout in 'ms'.
   * @return                Negative on error, otherwise the number of bytes
   *                        stored on the 'buffer'. In case of timeout, the
   *                        'return_value' < 'block_size'
   */
  //int ReadBlock(unsigned char *buffer, int block_size, int timeout_ms = -1);


  /**
   * Writes data to serial port. This function blocks until the whole
   * block is sent (to buffer atleast). Timeout may be used to terminate
   * if operation cannot be completed fast enough.
   *
   * @param buffer          Buffer to write data from, must be atleast
   *                        'block_size' bytes.
   * @param block_size      Bytecount to write to device.
   * @param timeout_ms      Timeout in 'ms'.
   * @return                Negative on error, otherwise the number of bytes
   *                        wrote out. In case of timeout, the
   *                        'return_value' < 'block_size'
   */
  //int WriteBlock(unsigned char *buffer, int block_size, int timeout_ms = -1);


  /**
   * WaitToRead, matches select(). See definition from 'bus.hpp'
   *
   */
  EBusStatus WaitToRead(const int aTimeout_ms = -1);


  /**
   * WaitToWrite, matches select(). See definition from 'bus.hpp'
   *
   */
  EBusStatus WaitToWrite(const int aTimeout_ms = -1);


  /**
   * Closes serial device (Frees it for others)
   *
   * @return                KBusStatusOK on ok, KBusStatusError on error.
   */
  EBusStatus Close(void);


  /**
   * Flushes serial buffers == Clears incoming and outgoing data buffers.
   *
   * @return         Zero on success, negative value on error.
   */
  int Flush(void);

private:
  CSerialStd(const CSerialStd &) :
    CSerial(0,"serial"),
    iPortfd(0),
    iOldPortSet(NULL),
    iNewPortSet(NULL) {}
  CSerialStd& operator=(const CSerialStd &) { return *this; }

  int iPortfd;

  struct termios *iOldPortSet;
  struct termios *iNewPortSet;
};

#endif //SERIALSTD












